home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 1
/
CU Amiga Magazine CD-ROM Special Edition (1995)(EMAP Images)(GB)[Issue 1995-11].iso
/
Aminet
/
comm
/
tcp
/
AmigaTCP.lha
/
AmigaTCP
/
src
/
amiga.c
next >
Wrap
C/C++ Source or Header
|
1989-06-24
|
15KB
|
654 lines
/*
* Modifications to existing pc.c module are --
*
* Copyright (c) 1987
* Louis A. Mamakos
*
* This work, or any derivations thereof may be used for non-commercial
* purposes only. So there.
*/
/* OS- and machine-dependent stuff for the Commodore-Amiga 1000 */
#define AMIGAVERSION "3"
#include <exec/types.h>
#include <functions.h>
/* for Manx Aztec C, get func returns */
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <devices/console.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <stdio.h>
#include "machdep.h"
#include "amiga.h"
#include "mbuf.h"
#include "internet.h"
#include "iface.h"
#include "cmdparse.h"
#include "slip.h"
#include "timer.h"
#include "netuser.h"
#include "ip.h"
#include "tcp.h"
#ifdef TRACE
#include "trace.h"
#endif
static char *copyright_notice[2] = {
"AMIGA port of KA9Q TCP/IP (C) Copyright 1987 Louis A. Mamakos\r\n",
"for non-commercial, non-profic use only\r\n"};
struct asy asy[ASY_MAX];
void *malloc();
void setiss();
/* Interface list header */
struct interface *ifaces;
struct IntuitionBase *IntuitionBase;
static char banner[80];
static struct NewWindow nw = {
0, 0, 640, 200, /* left, top, (max) width, (max) height */
0, 1, /* detail pen, block pen */
0, /* IDCMP flags */
SMART_REFRESH | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING |
SIZEBBOTTOM | ACTIVATE | NOCAREREFRESH, /* window flags */
NULL, NULL, /* gadget, checkmark */
(UBYTE *)&banner[0], /* title of window */
NULL, NULL, /* screen, bitmap */
200, 50, -1, -1, /* sizing limits */
WBENCHSCREEN, /* on the workbench */
};
APTR oldwindowptr;
struct Process *mytask;
struct MsgPort *keyboard, *consinp, *consoutp, *serinp, *seroutp,
*timerp;
struct IOExtSer serin, serout;
struct IOStdReq consin, consout;
struct timerequest tr;
struct Window *win;
char InputCharacter;
int timeropen, serialopen;
#ifdef AMIGADEVDRV
int DeviceSignal;
#endif
struct timer worktimer; /* this is NOT a timer.device timer */
void worker();
#ifdef LATTICE
extern struct { short error; char *msg; } os_errlist[];
extern int _OSERR, os_nerr;
#endif
static
clean(why)
char *why;
{
int i;
#ifdef AMIGADEVDRV
if (DeviceSignal >= 0)
FreeSignal(DeviceSignal);
#endif
if (timeropen)
CloseDevice(&tr);
if (serialopen)
CloseDevice(&serin);
if (win)
CloseWindow(win);
if (consinp)
DeletePort(consinp);
if (consoutp)
DeletePort(consoutp);
if (serinp)
DeletePort(serinp);
if (seroutp)
DeletePort(seroutp);
if (timerp)
DeletePort(timerp);
mytask->pr_WindowPtr = oldwindowptr;
if (why) {
myoserr(why);
}
exit(0);
}
myoserr(why)
char *why;
{
int i;
fprintf(stderr, "%s: ", why);
#ifdef LATTICE
fprintf(stderr, "%d: ", _OSERR);
for(i = 0; os_errlist[i].error < os_nerr; i++)
if (os_errlist[i].error == _OSERR)
fprintf(stderr, os_errlist[i].msg);
#endif
fprintf(stderr, "\r\n");
}
/* Called at startup time to set up console I/O, memory heap */
ioinit()
{
extern char major_rev[], minor_rev[];
struct Screen *scr;
mytask = (struct Process *) FindTask((char *) NULL);
oldwindowptr = mytask->pr_WindowPtr;
mytask->pr_WindowPtr = (APTR) -1; /* disable DOS requestors */
if ((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 33L)) == NULL)
clean("No intuition: Version 1.2 of Amiga Systems Software required");
sprintf(banner,
#ifdef AMIGADEVDRV
"KA9Q Internet Protocol Package, v%s.%s (Amiga version %sD)",
#else
"KA9Q Internet Protocol Package, v%s.%s (Amiga version %s)",
#endif
major_rev, minor_rev, AMIGAVERSION);
/*
* Try to determine the size of the workbench screen
*/
scr = malloc(sizeof(struct Screen));
if (scr==NULL)
clean("Can't alloc screen");
if (GetScreenData(scr, (ULONG) sizeof(struct Screen),
WBENCHSCREEN, NULL) == TRUE) {
nw.Width = scr->Width;
nw.Height = scr->Height-20;
nw.TopEdge = 19;
} else
fprintf(stderr, "Can't GetScreenData()\n");
free((char *)scr);
if ((win = OpenWindow(&nw)) == NULL)
clean("Can't open window");
if ((consinp = CreatePort("net:console in", 0L)) == NULL)
clean("Can't create console port");
if ((consoutp = CreatePort("net:console out", 0L)) == NULL)
clean("Can't create console port");
if ((timerp = CreatePort("net:timer", 0L)) == NULL)
clean("Can't create timer port");
consin.io_Data = (APTR) win;
consin.io_Length = sizeof(struct Window);
if (OpenDevice("console.device", 0L, &consin, 0L) != 0L)
clean("Can't open console device");
consout = consin;
consin.io_Message.mn_ReplyPort = consinp;
consin.io_Length = 1;
consin.io_Data = (APTR) &InputCharacter;
consin.io_Command = CMD_READ;
SendIO(&consin);
consout.io_Message.mn_ReplyPort = consoutp;
consout.io_Command = CMD_WRITE;
/* create and start up timer */
tr.tr_node.io_Message.mn_ReplyPort = timerp;
if (OpenDevice("timer.device", UNIT_VBLANK, &tr, 0L) != 0L)
clean("Can't open timer");
#ifdef AMIGADEVDRV
if ((DeviceSignal = AllocSignal(-1)) == -1)
clean("Can't allocate device signal");
#endif
timeropen++;
tr.tr_node.io_Command = TR_GETSYSTIME;
DoIO(&tr);
#ifdef DEBUG
printf("System time is %ld\n", tr.tr_time.tv_secs);
#endif
setiss(tr.tr_time.tv_secs);
tr.tr_node.io_Command = TR_ADDREQUEST;
tr.tr_time.tv_secs = 0;
tr.tr_time.tv_micro = MSPTICK*1000L; /* convert to microseconds */
SendIO(&tr);
set_timer(&worktimer, 1500); /* set for 1.5 seconds */
worktimer.func = worker;
#ifdef AMIGADEVDRV
DriverInit(); /* install internet.device driver */
#endif
start_timer(&worktimer);
}
/* Called just before exiting to restore console state */
iostop()
{
while(ifaces != NULLIF){
if(ifaces->stop != NULLFP)
(*ifaces->stop)(ifaces);
ifaces = ifaces->next;
}
#ifdef AMIGADEVDRV
DriverShutdown();
#endif
clean((char *)0);
}
#define BUFMAXCNT 150
static char conbuf[BUFMAXCNT];
static int concnt = 0;
int
amigaputchar(c)
char c;
{
conbuf[concnt++] = c;
if ((c == '\n') || (concnt == BUFMAXCNT))
amigaflush();
return c;
}
amigaflush()
{
if (concnt == 0)
return;
consout.io_Data = (APTR) conbuf;
consout.io_Length = concnt;
consout.io_Command = CMD_WRITE;
DoIO(&consout);
concnt = 0;
}
/*
* Begin terrible, horrible hack. All output should be printed upon (into?)
* the window we opened before. Here goes nothing...
*/
void
printf(a, b, c, d, e, f, g, h, i, j, k)
char *a;
int b, c, d, e, f, g, h, i, j, k;
{
if (concnt)
amigaflush();
sprintf(conbuf, a, b, c, d, e, f, g, h, i, j, k);
consout.io_Data = (APTR) conbuf;
consout.io_Length = strlen(conbuf);
consout.io_Command = CMD_WRITE;
DoIO(&consout); /* no use in doing this async */
}
/* check active connections and update titles */
void
check_connections()
{
extern struct tcb *tcbs[NTCB];
register struct tcb *tcb;
register int i;
int newlisten, newopn;
static int listen = -1, opn = -1;
static msg[80];
newlisten = newopn = 0;
for(i=0; i<NTCB; i++)
for(tcb=tcbs[i]; tcb != NULLTCB; tcb = tcb->next)
if (tcb->state == LISTEN)
newlisten++;
else
newopn++;
if (newlisten != listen || newopn != opn) {
listen = newlisten;
opn = newopn;
sprintf(msg,
"Amiga Port by WA3YMH (TCP: listen: %d open: %d)", listen, opn);
SetWindowTitles(win, -1L, msg);
}
}
/* called every second or so */
void
worker()
{
check_connections();
start_timer(&worktimer);
}
#if 0
/* processes any messages that Intuition sends us */
void
Do_Intuition_Message(m)
register struct IntuiMessage *m;
{
ULONG class;
USHORT code, qualifier;
class = m->Class;
code = m->Code;
qualifier = m->Qualifier;
ReplyMsg((struct Message *) m); /* reply msg back to Intuition */
switch (class) {
case INTUITICKS:
check_connections();
break;
}
}
#endif
/*
* wait for something to happen
*/
eihalt()
{
register struct IntuiMessage *msg;
static ULONG mask = 0;
if (mask == 0L)
mask = 1L << consinp->mp_SigBit |
1L << serinp->mp_SigBit |
1L << timerp->mp_SigBit |
#ifdef AMIGDEVDRV
1L << DeviceSignal |
#endif
#if 0
1L << win->UserPort->mp_SigBit |
#endif
1L << seroutp->mp_SigBit;
(void) Wait(mask);
#if 0
while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
Do_Intuition_Message(msg);
#endif
}
/* checks the time then ticks and updates ISS */
void
check_time()
{
int32 iss();
if (CheckIO(&tr)) {
WaitIO(&tr);
(void) GetMsg(timerp);
tick();
(void)iss();
tr.tr_time.tv_secs = 0;
tr.tr_time.tv_micro = MSPTICK*1000L;
/* convert to microseconds */
SendIO(&tr);
}
}
/* Initialize asynch port "dev" */
/*
* We will make the bold and rash assumption that the asy link will be used
* for slip and slip-like stuff. That is, we assume that there is an
* an end-of-frame character that we can have the serial.device driver look
* for. Thus, we can fire up a single I/O request and have the whole frame
* come back at once.
*/
int
asy_init(dev, bufsize)
int16 dev;
unsigned bufsize;
{
char serinitstr[1];
int serinitlen;
serinitstr[0] = FR_END; /* initialize initialization string to a */
serinitlen = 1; /* frame end to flush receiver */
if (serialopen) {
printf("\namiga: Error - serial device already open.\n");
return 0;
}
if ((serinp = CreatePort("net:serin", 0L)) == NULL)
clean("Can't create serial input port");
if ((seroutp = CreatePort("net:serout", 0L)) == NULL)
clean("Can't create serial output port");
/*
* Open serial device.
*/
serin.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE; /* ? */
serin.io_Status = 0;
serin.io_RBufLen = bufsize;
asy[dev].speed = serin.io_Baud = 2400; /* default speed */
if (OpenDevice("serial.device", 0L, &serin, 0L) != 0L)
clean("Can't open serial device");
serialopen++;
serin.IOSer.io_Message.mn_ReplyPort = serinp;
serout = serin;
serout.IOSer.io_Message.mn_ReplyPort = seroutp;
asy[dev].buflen = bufsize;
/* alloc input buffer */
if((asy[dev].input_buffer = malloc(asy[dev].buflen)) == NULL)
clean("Can't allocate serial input buf");
serin.IOSer.io_Data = (APTR) asy[dev].input_buffer;
serin.IOSer.io_Length = asy[dev].buflen;
asy[dev].input_len = 0; /* clear input buffer */
serin.io_SerFlags = SERF_XDISABLED|SERF_EOFMODE|SERF_RAD_BOOGIE;
serin.IOSer.io_Flags = 0;
SendIO(&serin);
serout.IOSer.io_Data = (APTR) serinitstr;
serout.IOSer.io_Length = serinitlen;
serout.IOSer.io_Command = CMD_WRITE;
serout.IOSer.io_Flags = 0;
serout.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE;
DoIO(&serout);
}
int
asy_stop(iface)
struct interface *iface;
{
if (iface->dev >= ASY_MAX) {
fprintf(stderr, "asy_stop: bad dev %d\n", iface->dev);
return;
}
AbortIO(&serin);
AbortIO(&serout);
CloseDevice(&serin);
free(asy[iface->dev].input_buffer); /* release buffer */
serialopen--;
}
/* Set asynch line speed */
int
asy_speed(dev,speed)
int dev;
int speed;
{
if (serialopen == 0)
return;
AbortIO(&serin);
WaitIO(&serin);
(void) GetMsg(serinp);
asy[dev].speed = serin.io_Baud = speed;
serin.io_ReadLen = 8;
serin.io_WriteLen = 8;
serin.io_StopBits = 1;
serin.io_TermArray.TermArray0 = serin.io_TermArray.TermArray1 =
(ULONG)FR_END << 24 | (ULONG)FR_END << 16 | FR_END << 8 | FR_END;
serin.IOSer.io_Command = SDCMD_SETPARAMS;
serin.IOSer.io_Flags = 0;
DoIO(&serin);
if (serin.IOSer.io_Error)
printf("Bad I/O status %d on SETPARAMS\n",
serin.IOSer.io_Error);
serin.IOSer.io_Command = CMD_READ;
serin.IOSer.io_Data = (APTR) asy[dev].input_buffer;
serin.IOSer.io_Length = asy[dev].buflen;
asy[dev].input_len = 0; /* clear input buffer */
serin.io_SerFlags = SERF_XDISABLED|SERF_EOFMODE|SERF_RAD_BOOGIE;
serin.IOSer.io_Flags = 0; /* no quick I/O */
SendIO(&serin);
}
/* Send a buffer to serial transmitter */
asy_output(dev,buf,cnt)
unsigned dev;
char *buf;
unsigned short cnt;
{
/*
* We 'know' that the transmitter is ready since we would not have
* been called unless the previous I/O has been completed.
*/
WaitIO(&serout);
GetMsg(seroutp);
serout.IOSer.io_Data = (APTR) buf;
serout.IOSer.io_Length = cnt;
serout.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE;
serout.IOSer.io_Flags = 0; /* no quick I/O */
serout.IOSer.io_Command = CMD_WRITE;
SendIO(&serout);
}
/* Read characters from the keyboard, translating them to "real" ASCII
* If none are ready, return the -1 from kbraw()
*/
kbread()
{
char c;
if (CheckIO(&consin)) {
WaitIO(&consin);
(void) GetMsg(consinp);
c = InputCharacter;
consin.io_Length = 1;
consin.io_Data = (APTR) &InputCharacter;
consin.io_Command = CMD_READ;
SendIO(&consin); /* start next read up */
return (c & 0xff);
}
return -1; /* nuthin here */
}
/* Receive characters from asynch line
* Returns count of characters read
*/
unsigned
asy_recv(dev,buf,cnt)
int dev;
char *buf;
unsigned cnt;
{
register int actual = 0;
register long error;
if (asy[dev].input_len == 0) { /* if buffer is empty.. */
if (CheckIO(&serin) == NULL) /* see if I/O has completed */
return 0; /* nope, not yet. */
if (error = WaitIO(&serin))
printf("(SERIN) WaitIO returns %d\n", error);
if (serin.IOSer.io_Error)
printf("Bad I/O stat %d (SERIN)\n",
serin.IOSer.io_Error);
(void) GetMsg(serinp);
/* input has completed. fill in state variables */
asy[dev].input_len = serin.IOSer.io_Actual;
asy[dev].input_p = asy[dev].input_buffer;
#ifdef TRACE
if (trace & 0x40000000) {
int a, n, l = asy[dev].input_len;
unsigned char *b = asy[dev].input_buffer;
a = 0;
printf("Raw serial input:\r\n");
while (l) {
n = min(l, 16);
fmtline(a, b, n);
a += n;
b += n;
l -= n;
}
fflush(stdout);
}
#endif
}
if (asy[dev].input_len) { /* any chars in buffer left? */
actual = min(asy[dev].input_len, cnt);
if (actual == 1)
*buf = *asy[dev].input_p; /* usual case */
else
movmem(asy[dev].input_p, buf, actual);
asy[dev].input_len -= actual;
asy[dev].input_p += actual;
}
if (asy[dev].input_len == 0) { /* if buffer is now empty */
serin.IOSer.io_Command = CMD_READ;
serin.IOSer.io_Data = (APTR) asy[dev].input_buffer;
serin.IOSer.io_Length = asy[dev].buflen;
serin.io_SerFlags =
SERF_XDISABLED|SERF_EOFMODE|SERF_RAD_BOOGIE;
serin.IOSer.io_Flags = 0; /* no quick I/O */
SendIO(&serin);
}
return actual;
}
int
stxrdy(dev)
{
return (CheckIO(&serout) != NULL);
}
/* Create a directory listing in a temp file and return the resulting file
* descriptor. If full == 1, give a full listing; else return just a list
* of names.
*
* This function is very dependent on the workings of Aztec standard I/O;
* it uses their mechanism for generating and deleting temporary files.
*/
FILE *
dir(path,full)
char *path;
int full;
{
/*return (FILE *)NULL;*/
return(0L);
}
#if 0
bcmp(a,b,n)
register char *a,*b;
register int16 n;
{
while(n-- != 0){
if(*a++ != *b++)
return 1;
}
return 0;
}
#endif